#ifndef THREADPOOL_H
#define THREADPOOL_H
/*
* 使用C++ 11标准的thread库的线程池
*/
#include <thread>
#include <cstdio>
#include <iostream>
#include <vector>
#include <memory>//智能指针的头文件
#include <queue>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <unordered_map>

enum class PoolMode
{
	MODE_FIXED,//固定数量的线程
	MODE_CACHED,//线程可自动增长
};

//C++17 Any 上帝类（万能容器）的简单实现
class Any
{
public:
	Any() = default;
	~Any() = default;
	//禁用左值引用的拷贝构造
	Any(const Any&) = delete;
	Any& operator=(const Any&) = delete;
	//右值引用的拷贝构造
	Any(Any&&) = default;
	Any& operator=(Any&&) = default;

	template<class T>
	Any(T data) :base_(std::make_unique<Derive<T>>(data))
	{

	}

	template<class T>
	T cast()
	{
		//基类指针转换为派生类指针（用来检查用户转换的类型是否正确），base_.get()把智能指针转换为原来的指针类型
		Derive<T>* pd = dynamic_cast<Derive<T>*>(base_.get());
		if (nullptr == pd)
		{
			throw "type is unmatch!";
		}
		return pd->data_;
	}
private:

	class Base
	{
	public:
		//虚析构可以在析构时调用派生类的析构函数
		virtual ~Base() = default;
	};
	
	template<class T>
	class Derive:public Base
	{
	public:
		Derive(T data) :data_(data)
		{

		}
		T data_;
	};


private:
	std::unique_ptr<Base> base_;
};

//实现C++20 的信号量
class Semaphore
{
public:
	~Semaphore() = default;
	Semaphore(int count = 0);
	void wait();
	void post();
private:
	int count_;
	std::mutex mtx_;
	std::condition_variable cond_;
};

//task前置声明
class Task;

//实现接受提交到线程池的task任务执行完成后的返回值类型Result
class Result
{
public:
	//Result(const Result&) = delete;
	//Result& operator=(const Result&) = delete;
	//Result(Result&&) = default;
	//Result& operator=(Result&&) = default;
	Result(std::shared_ptr<Task> task, bool isValid = true);
	~Result() = default;
	Any get();
	void setVal(Any any);
private:
	Any any_;
	Semaphore sem_;
	//指向返回值所对应的任务
	std::shared_ptr<Task> task_;
	//返回值是否有效
	std::atomic_bool isValid_;
};




//任务类型
class Task
{
public:
	Task();
	~Task() = default;
	//一个包含了本类中run方法的执行函数
	void exec();
	//设置result_的值
	void setResult(Result* res);
	virtual Any run() = 0;
	int getTaskId();
protected:
	int taskId_;
private:
	static int autoincrement_;
	Result* result_;
};
//线程类型
class Thread
{
public:
	//线程函数对象类型
	using ThreadFunc = std::function<void(int)>;

	//线程构造
	Thread(ThreadFunc function);
	~Thread();
	//启动线程
	void start();
	int getId() const;
private:
	ThreadFunc func;
	static int generateId_;
	int threadId_;//保存线程id（自增长的编号，不是真的线程id）
};

//线程池类型
class ThreadPool
{
public:
	ThreadPool();
	~ThreadPool();
	void setMode(PoolMode mode);//设置线程池的工作模式是固定线程还是动态线程

	void setMaxTaskSize(int maxSize);//设置task任务队列的任务最大值

	void setMaxThreadSize(int size);

	Result submitTask(std::shared_ptr<Task> spTask);//给线程池添加任务，任务使用智能指针

	void start(int initThreadSize = 4);//开启线程池

	//禁止拷贝构造线程池和赋值操作
	ThreadPool(const ThreadPool&) = delete;
	ThreadPool& operator=(const ThreadPool&) = delete;
private:
	//定义线程函数
	void threadFunc(int threadId);

	//检查pool的运行状态（是否在运行）
	bool checkRunningState() const;

private:
	//std::vector<std::unique_ptr<Thread>> threads;//线程列表(已经舍弃）
	std::unordered_map<int, std::unique_ptr<Thread>> threads;//线程列表


	size_t initThreadSize_;//初始线程数量
	std::atomic_uint currentThreadSize_;//当前线程数
	int maxThreadSize_;//线程数量的最大值
	std::atomic_uint idleThreadSize_;//记录空闲线程的数量

	std::queue<std::shared_ptr<Task>> taskQue_;//任务队列，使用强智能指针
	std::atomic_uint taskSize_;//当前任务数量，使用原子类型可以节省互斥锁开销
	int maxTaskSize_;//任务最大数量

	std::mutex taskQueMtx;//保证任务队列的线程安全
	std::mutex exitMtx_;
	std::condition_variable notFull;//表示任务不满
	std::condition_variable notEmpty;//表示不空；
	std::condition_variable exitCond_;//线程结束信号
	
	PoolMode poolMode_;//当前线程池的工作模式
	std::atomic_bool isPoolRunning_;
};






#endif
